{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id</th>\n",
       "      <th>locale</th>\n",
       "      <th>birthyear</th>\n",
       "      <th>gender</th>\n",
       "      <th>joinedAt</th>\n",
       "      <th>location</th>\n",
       "      <th>timezone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>3197468391</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1993</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-02T06:40:55.524Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>480.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3537982273</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1992</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-09-29T18:03:12.111Z</td>\n",
       "      <td>Medan  Indonesia</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>823183725</td>\n",
       "      <td>en_US</td>\n",
       "      <td>1975</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-06T03:14:07.149Z</td>\n",
       "      <td>Stratford  Ontario</td>\n",
       "      <td>-240.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1872223848</td>\n",
       "      <td>en_US</td>\n",
       "      <td>1991</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-11-04T08:59:43.783Z</td>\n",
       "      <td>Tehran  Iran</td>\n",
       "      <td>210.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>3429017717</td>\n",
       "      <td>id_ID</td>\n",
       "      <td>1995</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-09-10T16:06:53.132Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      user_id locale birthyear  gender                  joinedAt  \\\n",
       "0  3197468391  id_ID      1993    male  2012-10-02T06:40:55.524Z   \n",
       "1  3537982273  id_ID      1992    male  2012-09-29T18:03:12.111Z   \n",
       "2   823183725  en_US      1975    male  2012-10-06T03:14:07.149Z   \n",
       "3  1872223848  en_US      1991  female  2012-11-04T08:59:43.783Z   \n",
       "4  3429017717  id_ID      1995  female  2012-09-10T16:06:53.132Z   \n",
       "\n",
       "             location  timezone  \n",
       "0    Medan  Indonesia     480.0  \n",
       "1    Medan  Indonesia     420.0  \n",
       "2  Stratford  Ontario    -240.0  \n",
       "3        Tehran  Iran     210.0  \n",
       "4                 NaN     420.0  "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_csv('users.csv')\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "38209"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n_records = df.shape[0]\n",
    "n_records"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 38209 entries, 0 to 38208\n",
      "Data columns (total 7 columns):\n",
      "user_id      38209 non-null int64\n",
      "locale       38209 non-null object\n",
      "birthyear    38209 non-null object\n",
      "gender       38100 non-null object\n",
      "joinedAt     38152 non-null object\n",
      "location     32745 non-null object\n",
      "timezone     37773 non-null float64\n",
      "dtypes: float64(1), int64(1), object(5)\n",
      "memory usage: 2.0+ MB\n"
     ]
    }
   ],
   "source": [
    "df.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "38209"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def get_uniqueUsers():\n",
    "    uniqueUsers = set()\n",
    "    for i in range(n_records):\n",
    "        uniqueUsers.add(df.loc[i, 'user_id'])\n",
    "        \n",
    "    n_events = len(uniqueUsers)\n",
    "    return n_events\n",
    "\n",
    "n_users = get_uniqueUsers()\n",
    "n_users"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>locale</th>\n",
       "      <th>birthyear</th>\n",
       "      <th>gender</th>\n",
       "      <th>joinedAt</th>\n",
       "      <th>timezone</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>id_ID</td>\n",
       "      <td>1993</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-02T06:40:55.524Z</td>\n",
       "      <td>480.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>id_ID</td>\n",
       "      <td>1992</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-09-29T18:03:12.111Z</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>en_US</td>\n",
       "      <td>1975</td>\n",
       "      <td>male</td>\n",
       "      <td>2012-10-06T03:14:07.149Z</td>\n",
       "      <td>-240.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>en_US</td>\n",
       "      <td>1991</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-11-04T08:59:43.783Z</td>\n",
       "      <td>210.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>id_ID</td>\n",
       "      <td>1995</td>\n",
       "      <td>female</td>\n",
       "      <td>2012-09-10T16:06:53.132Z</td>\n",
       "      <td>420.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  locale birthyear  gender                  joinedAt  timezone\n",
       "0  id_ID      1993    male  2012-10-02T06:40:55.524Z     480.0\n",
       "1  id_ID      1992    male  2012-09-29T18:03:12.111Z     420.0\n",
       "2  en_US      1975    male  2012-10-06T03:14:07.149Z    -240.0\n",
       "3  en_US      1991  female  2012-11-04T08:59:43.783Z     210.0\n",
       "4  id_ID      1995  female  2012-09-10T16:06:53.132Z     420.0"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = df.drop(['user_id'], axis=1)\n",
    "df = df.drop(['location'], axis=1)\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "import datetime\n",
    "import hashlib\n",
    "import locale\n",
    "\n",
    "from collections import defaultdict\n",
    "from sklearn.preprocessing import normalize\n",
    "\n",
    "class FeatureEng:\n",
    "    def __init__(self):\n",
    "        self.localeIdMap = defaultdict(int)\n",
    "        for i, l in enumerate(locale.locale_alias.keys()):\n",
    "          self.localeIdMap[l] = i + 1\n",
    "        \n",
    "        self.genderIdMap = defaultdict(int, {'NaN': 0, \"male\":1, \"female\":2})\n",
    "  \n",
    "    def getLocaleId(self, locstr):\n",
    "        return self.localeIdMap[locstr.lower()]\n",
    "\n",
    "    def getGenderId(self, genderStr):\n",
    "        return self.genderIdMap[genderStr]\n",
    "\n",
    "    def getJoinedYearMonth(self, dateString):\n",
    "        try:\n",
    "            dttm = datetime.datetime.strptime(dateString, \"%Y-%m-%dT%H:%M:%S.%fZ\")\n",
    "            return (dttm.year-2010)*12 + dttm.month\n",
    "        except:  \n",
    "          return 0\n",
    "\n",
    "    def getBirthYearInt(self, birthYear):\n",
    "        try:\n",
    "          return 0 if birthYear == \"None\" else int(birthYear)\n",
    "        except:\n",
    "          return 0\n",
    "\n",
    "    def getTimezoneInt(self, timezone):\n",
    "        try:\n",
    "          return int(timezone)\n",
    "        except: \n",
    "          return 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "FE = FeatureEng()\n",
    "\n",
    "cols = ['LocaleId', 'BirthYearInt', 'GenderId', 'JoinedYearMonth', 'TimezoneInt']\n",
    "n_cols = len(cols)\n",
    "userMatrix = np.zeros((df.shape[0],n_cols), dtype=np.int)\n",
    "\n",
    "for i in range(df.shape[0]): \n",
    "    userMatrix[i, 0] = FE.getLocaleId(df.loc[i,'locale'])\n",
    "    userMatrix[i, 1] = FE.getBirthYearInt(df.loc[i,'birthyear'])\n",
    "    userMatrix[i, 2] = FE.getGenderId(df.loc[i,'gender'])\n",
    "    userMatrix[i, 3] = FE.getJoinedYearMonth(df.loc[i,'joinedAt'])\n",
    "    userMatrix[i, 4] = FE.getTimezoneInt(df.loc[i,'timezone'])\n",
    "\n",
    "userMatrix = normalize(userMatrix, norm=\"l1\", axis=0, copy=False)\n",
    "\n",
    "df_FE = pd.DataFrame(data=userMatrix, columns=cols) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>LocaleId</th>\n",
       "      <th>BirthYearInt</th>\n",
       "      <th>GenderId</th>\n",
       "      <th>JoinedYearMonth</th>\n",
       "      <th>TimezoneInt</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.000020</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000036</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.000020</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.000034</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>-0.000018</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.000034</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000016</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.000020</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   LocaleId  BirthYearInt  GenderId  JoinedYearMonth  TimezoneInt\n",
       "0  0.000020      0.000027  0.000019         0.000026     0.000036\n",
       "1  0.000020      0.000027  0.000019         0.000026     0.000031\n",
       "2  0.000034      0.000027  0.000019         0.000026    -0.000018\n",
       "3  0.000034      0.000027  0.000038         0.000027     0.000016\n",
       "4  0.000020      0.000027  0.000038         0.000026     0.000031"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_FE.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.cluster import MiniBatchKMeans\n",
    "import time\n",
    "from sklearn import metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def K_cluster_analysis(K, X_train):\n",
    "    start = time.time()\n",
    "    print(\"K-means begin with clusters: {}\".format(K));\n",
    "    mb_kmeans = MiniBatchKMeans(n_clusters = K)\n",
    "    mb_kmeans.fit(X_train)\n",
    "#     CH_score = metrics.silhouette_score(X_train,mb_kmeans.predict(X_train))\n",
    "    CH_score = metrics.calinski_harabaz_score(X_train,mb_kmeans.predict(X_train))\n",
    "\n",
    "    end = time.time()\n",
    "    print(\"CH_score: {}, time elaps:{}\".format(CH_score, int(end-start)))\n",
    "    \n",
    "    return CH_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "K-means begin with clusters: 20\n",
      "CH_score: 39503.467222911335, time elaps:0\n",
      "K-means begin with clusters: 40\n",
      "CH_score: 48459.96044670256, time elaps:0\n",
      "K-means begin with clusters: 80\n",
      "CH_score: 44642.81517001615, time elaps:0\n"
     ]
    }
   ],
   "source": [
    "Ks = [20, 40, 80]\n",
    "CH_scores = []\n",
    "\n",
    "for K in Ks:\n",
    "    ch = K_cluster_analysis(K, df_FE)\n",
    "    CH_scores.append(ch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7f5d89fe8278>]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYcAAAD8CAYAAACcjGjIAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAAIABJREFUeJzt3Xm81nP6x/HX5bRIlkhIJ46IZAzDmWQYRrbCMPP7MbIzaDLZt9HQdtJQ9jWSLFmy02RpGpnBDKmEkHQk1bEU2RtpuX5/XN/z60ynOvv53sv7+Xich/v+3N9z39dX576v+/p+NnN3REREKlon7QBERCTzKDmIiEglSg4iIlKJkoOIiFSi5CAiIpUoOYiISCVKDiIiUomSg4iIVKLkICIilTRJO4Da2nTTTb2oqCjtMEREssbUqVM/d/c21Tk2a5NDUVERU6ZMSTsMEZGsYWYfVfdYXVYSEZFKlBxERKQSJQcREalEyUFERCpRchARkUqUHEREpBIlBxERqUTJQVI3Zw4MHw4LF6YdiYiUU3KQ1PXqBX/8IxQWwoknwquvgrY2F0mXkoOk6sUXYcIEOP98OP10ePJJ2HNP2H13GDkSvv8+7QhF8pOSg6TGHS67DNq2hcsvh5tvhrKyuMS0dGkki3bt4Lzz4P33045WJL8oOUhq/v53eOkluPRSaNEi2jbYAHr3hrfeiqqiR49IGjvsAAcdFJXFsmXpxi2SD8yz9OJucXGxa+G97OUel48+/hhmzYLmzdd87KefxiWm22+H+fOjb+IPf4jKYvPNGy9mkWxnZlPdvbg6x6pykFQ88wxMmgT9+689MQBssUVcfvrwQ3jiCejUCfr1g/bt4ZhjovrI0u84IhlLlYM0OvfocP76a3jvPWjatObPMXMm3HYb3HVXPM/OO8eIp+OOi0tTIlJZg1QOZlZgZtPMbFxyf38ze93M3jCzl81su6S9uZk9ZGalZjbJzIoqPEffpH2mmR1cob170lZqZpdUNybJTk88AdOmwcCBtUsMEH0Q110XHdh33AEFBXDGGdGBfdZZ8O679RqySN6pyWWlc4AZFe4PB45z912BB4DLkvZTgS/dfTvgOmAogJl1BnoCOwHdgVuThFMA3AL0ADoDxyTHSg5avjwuJXXqBMceW/fna9kSTjsNXn8dXnkFjjgCRoyAnXaC/faDRx6JkU8iUjPVSg5mVggcCoys0OzAhsntjYCPk9tHAPcktx8F9jczS9rHuPsSd/8QKAW6JD+l7j7b3X8ExiTHSg56+GF4552oGgoK6u95zaBrVxg9Ojqtr7wy+ih+9zvYeut4vbKy+ns9kVxX3crheuBiYEWFttOAZ8xsPnACcGXS3g6YB+Duy4CvgdYV2xPzk7Y1tVdiZr3MbIqZTVmotRayzrJl8SG9885w1FEN9zpt2sCf/gQffAB//SvsuiuUlESSOPJIeOEFdWCLVKXK5GBmhwEL3H3qKg+dBxzi7oXAXcC1DRDff3H3Ee5e7O7FbdpUa49sySD33ReT2UpKYJ1GGCdXUACHHRYjo2bNisl0L7wA3bpB585w003RmS0ilVXnLboXcLiZzSEu+XQzs6eBXdx9UnLMQ8AvkttlQHsAM2tCXHL6omJ7ojBpW1O75JClSyMp7L579As0tm23hauuiktOd98NG24IZ58dHdjlk+5EZKUqk4O793X3QncvIjqUJxJ9AhuZ2fbJYQeysrN6LHBScvtIYKLHeNmxQM9kNNM2QEfgNWAy0NHMtjGzZslrjK2Xs5OMcddd0QcweHD0D6SlRQs46aSYYzF5cvRJ3HMP7LIL7L03PPgg/PhjevGJZIpaFfdJX8LpwGNm9ibR53BR8vCdQGszKwXOBy5Jfucd4GHgXeA5oI+7L0+e60xgPJFgHk6OlRzxww+RFPbcE7p3TzualYqLYdSo6Ki++uqYiX3ssTG57tJLYe7ctCMUSY8mwUmDu+mmuITz/PNxvT9TrVgRK8TecguMGxcVzq9/HZPrDjigcfpJRBqSls+QjLF4MQwZAr/6VWYnBogP/4MPhrFjYfbsGPH0739HW6dOMenuyy/TjlKkcSg5SIO69Vb47LO4rJRNiorgL3+BefPg/vtjeOz550cH9qmnxqQ7kVym5CAN5ttvYejQ+Oa9995pR1M7zZtHP8S//hVLfpxwAowZE6OuunaFe++NPhWRXKPkIA3mxhvh889jCGsu2HXXWDa8rAxuuAG++ipGPhUWxiWoDz9MO0KR+qPkIA3iq69iBNDhh0OXLmlHU79atYoO9hkzYsOiffeFa66JuRSHHhqT7pYvTztKkbpRcpAGce21kSBypWpYHTPYf3947DGYMyf2mHj99UgQHTvCsGFROYlkIyUHqXdffAHXXx/rGO2yS9rRNI7CQhg0CD76CB56CLbaKi41FRaunHSXpaPGJU8pOUi9u+oq+O67+LDMN82axazrf/wDpk+PkU2PPx6d1+WT7hYvTjtKkaopOUi9+uyzmPR27LGxuF0++8lPYkLdxx/HkN4lSyJZtGsXw2JnzUo7QpE1U3KQenXllfEhOGBA2pFkjg02iF3qpk+Hf/4zhvbedBNsv33cfuopdWBL5lFykHpTVgbDh8c19o4d044m85jBPvvEPIm5c6Oz/p134De/gQ4dYtLdZ5+lHaVIUHKQejNkSKxP1K9f2pFkvrZt4//TnDnRJ9GxYyz21779ykl36sCWNCk5SL2YMwdGjoz9nIuK0o4mezRpAr/9bcyXmDEjFvl75pmYUV4+6e6779KOUvKRkoPUi8GDY+G6Sy9NO5Ls1alTDAEuK4MRI+IyVO/e0YFdPulOpLEoOUidlZbGhjlnnBEfZFI3LVvC6afHWk7//nfMMr/99hj91a1bTLpbujTtKCXXKTlInQ0aFAvUXXJJ2pHkFrPYIGn06Fgd9oorYinxI4+MS3eDBsUwWZGGoOQgdfLuu7Gk9Zlnwuabpx1N7tpss0i+H3wQ+0389KcwcCBsvfXKSXfqwJb6pOQgdTJwIKy/Plx8cdqR5IeCgtid7tlnYxLdOedEZ/Z++62cdPfNN2lHKblAyUFq7Y034JFH4NxzoXXrtKPJP9ttFyvflpXBXXfBeutFBbfllisn3YnUlpKD1NqAAbF89fnnpx1JfmvRAk4+GSZPhtdeg6OOgrvvjktP5ZPufvwx7Sgl2yg5SK1MnhzXvi+8MBKEZIaf/zyqiPnzYwHEsjI45phYJbZfv+jYFqkOJQeplX794lLS2WenHYmsTuvWkbhnzYr+iS5dYgZ7UdHKSXcrVqQdpWQyJQepsZdfhvHjY/TMBhukHY2szTrrQPfuUeXNnh0DB15+GQ48EHbcMSbdffll2lFKJlJykBrr1w+22CKWepDsUVQUcyXmzYu5E61bw3nnxcTF8kl3IuWUHKRGJk6MMfV9+8boGMk+664Lxx8fs69ffz1uP/AA7LZbTLq77z744Ye0o5S0KTlItblH1VBYCL16pR2N1Ief/SzWcSori0tMixbBCSfE6rCXXBILKkp+UnKQanvuufi2edll8e1TckerVjGh7r33YMIE+OUvY7RThw4rJ92pAzu/mGfpnPvi4mKfMmVK2mHkDfcYJrloUXyANGuWdkTS0ObNi6rijjtiE6IOHWJy3SmnaNJjtjKzqe5eXJ1jVTlItTz1FEydCv37KzHki/btYyn2uXNjIl1hIVx0UXRgl0+6k9ylykGqtGJFbDyzZElsa9mkSdoRSVqmT4+tYEePjk2Iiotj1FrPnjFTWzKbKgepV48+Gh8KAwcqMeS7nXeGW2+NDuybb4bFi+H3v49q4sILY28PyQ2qHGStli+P1T4LCuCtt2JSlUg5d3jxxUgYjz8Oy5bBwQdDnz5wyCHxdyOZQ5WD1JsHHogO6JISJQapzAz23Rceegg++ig2IJo+PXav69AhJt0tWJB2lFIbqhxkjZYujSUWNtwwOqPN0o5IssHSpfDXv8beEhMnxgCGo46Kvok999TfUZpUOUi9uOee2HmspERvaKm+pk3hf/4Hnn8+dgrs3TuSxV57xSzsO+6A779PO0qpSrWTg5kVmNk0MxuX3DczG2Jm75vZDDM7u0L7jWZWamZvmdluFZ7jJDOblfycVKF9dzObnvzOjWb6KErbkiUxjHGPPeDQQ9OORrLVjjvCDTdEB/btt8fIt169YkOi8kl3kplqUjmcA8yocP9koD3Qyd13BMYk7T2AjslPL2A4gJltAgwA9gC6AAPMbOPkd4YDp1f4ve61OBepRyNHxvj2wYNVNUjdrb9+JIU33ohVYQ87LIbE7rgjHHDAys5syRzVSg5mVggcCoys0HwGUOLuKwDcvbzb6QjgXg+vAq3MrC1wMDDB3Re5+5fABKB78tiG7v6qRwfIvcBv6uPkpHb+859Y+3+ffeKNK1JfzOLy0v33x4ZEf/lL7Dnxv/8bq8YOHgyffJJ2lALVrxyuBy4GKq6usi1wtJlNMbNnzaxj0t4OqLjf1PykbW3t81fTLim57bZ4g6pqkIa02Waxuu/s2TED/yc/iRn4W20FRx8dQ2SzdLxMTqgyOZjZYcACd5+6ykPNgR+Snu87gFENEN+qsfRKktGUhQsXNvTL5aXvvovhhwccEJWDSEMrKIihr889B++/H7sLTpgQQ2TLJ919803aUeaf6lQOewGHm9kcol+hm5ndR3zDfzw55gngp8ntMqIvolxh0ra29sLVtFfi7iPcvdjdi9u0aVON0KWmbr4ZFi6MqkGksXXsCNdcE5ecRo2K1X/79IkZ2H36wNtvpx1h/qgyObh7X3cvdPcioCcw0d2PB54E9ksO2xd4P7k9FjgxGbXUFfja3T8BxgMHmdnGSUf0QcD45LFvzKxrMkrpROCpejxHqaavv4Zhw2J0UteuaUcj+Wy99WL118mTYdKk6JO4886oJPbdFx5+GH78Me0oc1td5jlcCfyvmU0HrgBOS9qfAWYDpcTlpj8CuPsiYDAwOfkpSdpIjhmZ/M4HwLN1iEtqqXw/4ZKStCMRCWbQpQvcfXcMhx02LJYSP/po2Hrr6KOYP7/Kp5Fa0AxpAWKfhm22ib6Gxx5LOxqRNVuxAsaPjxnYzzwTy7occUTMwO7WTYMo1kYzpKXGrr4avv021sYRyWTrrAM9esC4cTGD/8IL4Z//jC82O+4IN94IX32VdpTZT8lBWLAg3lA9e8ZwQpFssc02cOWVcWnp3nth441j5nW7disn3UntKDkIQ4fGxLcBA9KORKR21l0XTjgBXnklFok85hi47z742c9WTrpbsiTtKLOLkkOe+/jjGEd+wgmwww5pRyNSd7vtFsu/lJXBddfF0Ozjj49tT/v2jaXFpWpKDnnuiitiTZv+/dOORKR+bbwxnHtuLO73t79FBTFsWOwzUT7pbsWKqp8nXyk55LG5c2HEiNjmsUOHtKMRaRjrrAMHHghPPAFz5kT1MGlSdGpvv31Mulu0qMqnyTtKDnns8svjv5ddlm4cIo2lffv4u583Dx58ENq2jdFO7drFlySNjl9JySFPffBBLE/whz/EG0YknzRrFqPzXnoJ3nwTTj45Zl3//Ocx6e6ee2KQRj5TcshTJSWxY1ffvmlHIpKun/409pb4+ONYW+y77yJZFBbCRRfFF6l8pOSQh957L4b5nXlmlNUiEnul9+kD77wDL7wQs62vuy4WAzzkkJh0t3x52lE2HiWHPDRwILRoARdfnHYkIpnHDH71K3jkkRi0MWBAXHr69a9h221j0l0+7Big5JBnpk+Hhx6KIX5a9Vxk7bbcMpLDnDnw6KMxqq9v37jkVD7pLkuXp6uSkkOeGTAANtoILrgg7UhEskfTprFs+MSJ8O67MZBj7Fj4xS9g991j0t3336cdZf1ScsgjU6fGWO/zz48JQiJSc+WL+5WVxZa6y5bB6afHcNjzzovd7HKBkkMe6d8fNtkkLimJSN2sv35UEG++GUNiDzkklhHfYYeYdPfkk5E4spWSQ5545ZVY+/7ii2NUhojUDzPYe2944IGYXDdkCMycCb/9bawae/nl8OmnaUdZc0oOeaJfP9hssxi+KiINY/PN4c9/htmzo3Lo3Dnee1ttFSvFvvRS9nRgKznkgX/8A55/PkZZtGyZdjQiua9Jk9idbvz46IM488xY6G+ffVZOuvv227SjXDslhxznHt9cttwSevdOOxqR/NOxI1x7bXRg33lnLN3xxz9GB/aZZ8aku0yk5JDjJkyAl1+OxfXWXTftaETy13rrrVzc79VXo09i5MjYfXG//WLS3dKlaUe5knm2XABbRXFxsU/REopr5Q577BHbgL7/fnxjEZHM8fnnsQDm8OEx0a5t29jetHxobH0zs6nuXlydY1U55LBx42Dy5LispMQgknk23TRGEJaWwtNPx7amJSWw9dZw5JEx6S6t7++qHHLUihUxc/O772JGZ9OmaUckItUxezbcfnv0T3zxBXTqFH0UJ54YqxvUhSoH4fHH4Y03YrkMJQaR7NGhAwwdCvPnx74SG20EZ58dl5l6945Jd41BlUMOWr48hsu5x0J7BQVpRyQidTF1Ktx6a0y0a9ECPvkEmjev+fOocshzY8bEpaRBg5QYRHLB7rvHZaayslgfrTaJoaZUOeSYZctiVmaLFjBtWmyuLiICNascmjR0MNK4Ro+GWbPgqaeUGESk9vTxkUN+/DEuJf3857FrlYhIbalyyCGjRsFHH8UwOLO0oxGRbKbKIUf88EMsDbzXXnDQQWlHIyLZTpVDjrj99hjJMHq0qgYRqTtVDjng++/hiiugW7dYwEtEpK5UOeSAW26Bzz6LWdEiIvVBlUOW+/ZbGDYMevSAX/wi7WhEJFdUOzmYWYGZTTOzcau032hm31W439zMHjKzUjObZGZFFR7rm7TPNLODK7R3T9pKzeySup1Sfrnhhlicq6Qk7UhEJJfUpHI4B5hRscHMioGNVznuVOBLd98OuA4YmhzbGegJ7AR0B25NEk4BcAvQA+gMHJMcK1X48ku4+urYjrC4WnMeRUSqp1rJwcwKgUOBkRXaCoCrgItXOfwI4J7k9qPA/mZmSfsYd1/i7h8CpUCX5KfU3We7+4/AmORYqcK118LXX6tqEJH6V93K4XoiCayo0HYmMNbdP1nl2HbAPAB3XwZ8DbSu2J6Yn7StqV3W4vPP4frr4Xe/ixVYRUTqU5XJwcwOAxa4+9QKbVsCRwE3NWBsq4ull5lNMbMpCxcubMyXzjjDhsHixTBwYNqRiEguqs5Q1r2Aw83sEGBdYEPgHWAJUBpXjFjPzEqTfoYyoD0w38yaABsBX1RoL1eYtLGW9v/i7iOAERCrslbnBHPRp5/CzTfDccfBjjumHY2I5KIqKwd37+vuhe5eRHQoT3T3jd19C3cvStoXJ4kBYCxwUnL7yOR4T9p7JqOZtgE6Aq8Bk4GOZraNmTVLXmNsPZ5jzrniilhkr3//tCMRkVzVEJPg7gRGm1kpsIj4sMfd3zGzh4F3gWVAH3dfDmBmZwLjgQJglLu/0wBx5YR58+C22+CUU2C77ao+XkSkNrTZT5bp3TtWX501C7beOu1oRCSbaJvQHPXhh7FV4OmnKzGISMNScsgigwdDkyZw6aVpRyIiuU7JIUu8/z7ccw+ccQZsuWXa0YhIrlNyyBKDBsG668IlWnlKRBqBkkMWePttePBBOPts2GyztKMRkXyg5JAFBg6E9deHCy9MOxIRyRdKDhlu2jR47DE4/3xo3TrtaEQkXyg5ZLj+/WHjjeG889KORETyiZJDBps0CcaNg4sugo02SjsaEcknSg4ZrH9/aNMGzjor7UhEJN80xNpKUg9eegn+9rfY6W399dOORkTyjSqHDOQOl10GbdvGpDcRkcamyiEDPf88vPgi3HQTrLde2tGISD5S5ZBh3KFfP2jfPhbYExFJgyqHDPPss/DqqzBiBDRvnnY0IpKvVDlkkPKqoUMHOPnktKMRkXymyiGDPPkkvP56rL7atGna0YhIPlPlkCFWrIh5DTvsAMcdl3Y0IpLvVDlkiIcfjtVXx4yBgoK0oxGRfKfKIQMsWxYrr+68Mxx1VNrRiIiocsgI998PM2fC44/DOkrXIpIB9FGUsqVLY5e33XaD3/wm7WhERIIqh5TddRd8+CHcfDOYpR2NiEhQ5ZCiJUvg8suha1fo0SPtaEREVlLlkKI77oB586J6UNUgIplElUNKFi+GIUNg332hW7e0oxER+W+qHFIyfDh8+mnMb1DVICKZRpVDCr79Fq68Eg46CH75y7SjERGpTMkhBTfdBJ9/DoMHpx2JiMjqKTk0sq++gquugl//Grp0STsaEZHVU3JoZNddFwmipCTtSERE1kzJoRF98UUkhyOPhF13TTsaEZE1U3JoRFdfDd99F4vsiYhkMiWHRvLZZ3DjjXDMMbDTTmlHIyKydkoOjWTo0FguY8CAtCMREalatZODmRWY2TQzG5fcv9/MZprZ22Y2ysyaJu1mZjeaWamZvWVmu1V4jpPMbFbyc1KF9t3NbHryOzea5da0sLIyuPVWOPFE2H77tKMREalaTSqHc4AZFe7fD3QCdgZaAKcl7T2AjslPL2A4gJltAgwA9gC6AAPMbOPkd4YDp1f4ve61OJeM9Ze/rNwGVEQkG1QrOZhZIXAoMLK8zd2f8QTwGlCYPHQEcG/y0KtAKzNrCxwMTHD3Re7+JTAB6J48tqG7v5o8171Azuxs8NFHscDeqadCUVHa0YiIVE91K4frgYuBFas+kFxOOgF4LmlqB8yrcMj8pG1t7fNX054TBg+O3d0uvTTtSEREqq/K5GBmhwEL3H3qGg65FXjR3V+q18hWH0svM5tiZlMWLlzY0C9XZ6WlcPfd0Ls3FBZWebiISMaoTuWwF3C4mc0BxgDdzOw+ADMbALQBzq9wfBnQvsL9wqRtbe2Fq2mvxN1HuHuxuxe3adOmGqGna9AgaNYMLrkk7UhERGqmyuTg7n3dvdDdi4CewER3P97MTiP6EY5x94qXm8YCJyajlroCX7v7J8B44CAz2zjpiD4IGJ889o2ZdU1GKZ0IPFWvZ5mCGTPg/vvhrLNgiy3SjkZEpGbqsp/DbcBHwCvJyNPH3b0EeAY4BCgFFgOnALj7IjMbDExOfr/E3Rclt/8I3E2Meno2+clqAwdCy5Zw0UVpRyIiUnM1Sg7u/g/gH8nt1f5uMuKozxoeGwWMWk37FOAnNYklk735Zmzic9llsOmmaUcjIlJzmiHdAAYMgFat4IIL0o5ERKR2lBzq2eTJ8NRTkRhatUo7GhGR2lFyqGf9+0Pr1nDOOWlHIiJSe3XpkJZV/Otf8NxzMGwYbLBB2tGIiNSeKod61K8fbL459Fltd7yISPZQ5VBPXnghfm64AdZbL+1oRETqRpVDPXCPqqGwEHr1SjsaEZG6U+VQD8aPj/6G4cNh3XXTjkZEpO5UOdRRedVQVAS//33a0YiI1A9VDnU0dixMmQKjRsUieyIiuUCVQx2U7+7WsSOccELa0YiI1B9VDnXw2GPw1lux+moT/Z8UkRyiyqGWli+PNZQ6d4ajj047GhGR+qXvu7X04IOxZ8Ojj0JBQdrRiIjUL1UOtbB0aezXsOuu8Nvfph2NiEj9U+VQC/feCx98AH/9K6yj9CoiOUgfbTW0ZAmUlMAee8Chh6YdjYhIw1DlUEN33glz58Idd0DsjioikntUOdTAf/4DQ4bAL38JBx6YdjQiIg1HlUMN3HYbfPwxPPCAqgYRyW2qHKrp++/hyivhgANg333TjkZEpGEpOVTTzTfDggUweHDakYiINDwlh2r45pvY+vOQQ6Br17SjERFpeEoO1XD99bBoUQxhFRHJB0oOVVi0CK65JmZC77572tGIiDQOJYcqXHMNfPstDBqUdiQiIo1HyWEtFi6EG26IVVd33jntaEREGo+Sw1oMHRoT3wYOTDsSEZHGpeSwBp98ArfcEju87bBD2tGIiDQuJYc1uOIKWLYstgEVEck3Sg6rMXcu3H47nHIKdOiQdjQiIo1PyWE1hgyJ/152WbpxiIikRclhFbNnw6hR0KsXbLVV2tGIiKRDyWEVJSXQpAn8+c9pRyIikh4lhwpmzoTRo6FPH2jbNu1oRETSU+3kYGYFZjbNzMYl97cxs0lmVmpmD5lZs6S9eXK/NHm8qMJz9E3aZ5rZwRXauydtpWZ2Sf2dXs0MHAgtWsCf/pRWBCIimaEmlcM5wIwK94cC17n7dsCXwKlJ+6nAl0n7dclxmFlnoCewE9AduDVJOAXALUAPoDNwTHJso5o+HR56CM45B9q0aexXFxHJLNVKDmZWCBwKjEzuG9ANeDQ55B7gN8ntI5L7JI/vnxx/BDDG3Ze4+4dAKdAl+Sl199nu/iMwJjm2UQ0YABtsABdc0NivLCKSeapbOVwPXAysSO63Br5y92XJ/flAu+R2O2AeQPL418nx/9++yu+sqb3RvP46PPFEJIZNNmnMVxYRyUxVJgczOwxY4O5TGyGeqmLpZWZTzGzKwoUL6+15+/ePpHDuufX2lCIiWa06lcNewOFmNoe45NMNuAFoZWZNkmMKgbLkdhnQHiB5fCPgi4rtq/zOmtorcfcR7l7s7sVt6qlj4JVX4Omn4aKLYMMN6+UpRUSyXpXJwd37unuhuxcRHcoT3f044AXgyOSwk4Cnkttjk/skj090d0/aeyajmbYBOgKvAZOBjsnop2bJa4ytl7Orhv79YbPN4KyzGusVRUQyX5OqD1mjPwFjzOxyYBpwZ9J+JzDazEqBRcSHPe7+jpk9DLwLLAP6uPtyADM7ExgPFACj3P2dOsRVbf/8J/z973DttdCyZWO8oohIdrD4Up99iouLfcqUKbX+fXfYd1/44AMoLY35DSIiuczMprp7cXWOrUvlkNX+/nd46aXYs0GJQUTkv+Xl8hnuseLqVlvBqadWfbyISL7Jy8rh6afhtddg5Eho3jztaEREMk/eVQ4rVkC/frDttnDiiWlHIyKSmfKucnjiCXjjDbj3XmjaNO1oREQyU15VDsuXxxpKnTrBscemHY2ISObKq8ph8WLo2hV69ICCgrSjERHJXHmVHDbYIDqhRURk7fJ16kYgAAAEm0lEQVTqspKIiFSPkoOIiFSi5CAiIpUoOYiISCVKDiIiUomSg4iIVKLkICIilSg5iIhIJVm72Y+ZLQQ+quWvbwp8Xo/hpClXziVXzgN0LpkoV84D6nYuW7t7m+ocmLXJoS7MbEp1d0PKdLlyLrlyHqBzyUS5ch7QeOeiy0oiIlKJkoOIiFSSr8lhRNoB1KNcOZdcOQ/QuWSiXDkPaKRzycs+BxERWbt8rRxERGQtcjo5mFl7M3vBzN41s3fM7JykfRMzm2Bms5L/bpx2rFUxs3XN7DUzezM5l0FJ+zZmNsnMSs3sITNrlnas1WFmBWY2zczGJfez9TzmmNl0M3vDzKYkbVn39wVgZq3M7FEze8/MZpjZntl4Lma2Q/LvUf7zjZmdm43nAmBm5yXv+bfN7MHks6DB3y85nRyAZcAF7t4Z6Ar0MbPOwCXA8+7eEXg+uZ/plgDd3H0XYFegu5l1BYYC17n7dsCXwKkpxlgT5wAzKtzP1vMA2M/dd60wvDAb/74AbgCec/dOwC7Ev0/WnYu7z0z+PXYFdgcWA0+QhediZu2As4Fid/8JUAD0pDHeL+6eNz/AU8CBwEygbdLWFpiZdmw1PI/1gNeBPYjJME2S9j2B8WnHV434C4k3ZzdgHGDZeB5JrHOATVdpy7q/L2Aj4EOSfshsPpdV4j8I+Fe2ngvQDpgHbELs3DkOOLgx3i+5Xjn8PzMrAn4GTAI2d/dPkoc+BTZPKawaSS7FvAEsACYAHwBfufuy5JD5xB9TprseuBhYkdxvTXaeB4ADfzOzqWbWK2nLxr+vbYCFwF3J5b6RZtaS7DyXinoCDya3s+5c3L0MuBqYC3wCfA1MpRHeL3mRHMxsfeAx4Fx3/6biYx6pNyuGbLn7co9SuRDoAnRKOaQaM7PDgAXuPjXtWOrJ3u6+G9CDuGy5T8UHs+jvqwmwGzDc3X8GfM8ql12y6FwASK7DHw48supj2XIuSb/IEUTy3hJoCXRvjNfO+eRgZk2JxHC/uz+eNH9mZm2Tx9sS38Szhrt/BbxAlJOtzKxJ8lAhUJZaYNWzF3C4mc0BxhCXlm4g+84D+P9vdrj7AuK6dhey8+9rPjDf3Scl9x8lkkU2nku5HsDr7v5Zcj8bz+UA4EN3X+juS4HHifdQg79fcjo5mJkBdwIz3P3aCg+NBU5Kbp9E9EVkNDNrY2atktstiL6TGUSSODI5LOPPxd37unuhuxcRJf9Edz+OLDsPADNraWYblN8mrm+/TRb+fbn7p8A8M9shadofeJcsPJcKjmHlJSXIznOZC3Q1s/WSz7Pyf5cGf7/k9CQ4M9sbeAmYzsrr238m+h0eBrYiVnb9nbsvSiXIajKznwL3EKMV1gEedvcSM+tAfAPfBJgGHO/uS9KLtPrM7FfAhe5+WDaeRxLzE8ndJsAD7j7EzFqTZX9fAGa2KzASaAbMBk4h+Vsj+86lJfHB2sHdv07asvXfZRBwNDH6chpwGtHH0KDvl5xODiIiUjs5fVlJRERqR8lBREQqUXIQEZFKlBxERKQSJQcREalEyUFERCpRchARkUqUHEREpJL/AxljtXBgrdWoAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f5d99a37780>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(Ks, np.array(CH_scores), 'b-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "K-means begin with clusters: 30\n",
      "CH_score: 43692.700137384636, time elaps:0\n",
      "K-means begin with clusters: 35\n",
      "CH_score: 51195.78603300432, time elaps:0\n",
      "K-means begin with clusters: 40\n",
      "CH_score: 51909.464535601706, time elaps:0\n",
      "K-means begin with clusters: 45\n",
      "CH_score: 44690.8008665268, time elaps:0\n",
      "K-means begin with clusters: 50\n",
      "CH_score: 41056.45634255123, time elaps:0\n"
     ]
    }
   ],
   "source": [
    "Ks = [30,35,40,45,50]\n",
    "CH_scores = []\n",
    "\n",
    "for K in Ks:\n",
    "    ch = K_cluster_analysis(K, df_FE)\n",
    "    CH_scores.append(ch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7f5d89fd85c0>]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f5d8a001208>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(Ks, np.array(CH_scores), 'b-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MiniBatchKMeans(batch_size=100, compute_labels=True, init='k-means++',\n",
       "        init_size=None, max_iter=100, max_no_improvement=10, n_clusters=40,\n",
       "        n_init=3, random_state=None, reassignment_ratio=0.01, tol=0.0,\n",
       "        verbose=0)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "n_clusters = 40\n",
    "mb_kmeans = MiniBatchKMeans(n_clusters=n_clusters)\n",
    "mb_kmeans.fit(df_FE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_FE['cluster_40'] = mb_kmeans.predict(df_FE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_FE.to_csv('users_predict.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>LocaleId</th>\n",
       "      <th>BirthYearInt</th>\n",
       "      <th>GenderId</th>\n",
       "      <th>JoinedYearMonth</th>\n",
       "      <th>TimezoneInt</th>\n",
       "      <th>cluster_40</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000036</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.000030</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000019</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>-0.000018</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.000030</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000016</td>\n",
       "      <td>11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000027</td>\n",
       "      <td>0.000038</td>\n",
       "      <td>0.000026</td>\n",
       "      <td>0.000031</td>\n",
       "      <td>26</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   LocaleId  BirthYearInt  GenderId  JoinedYearMonth  TimezoneInt  cluster_40\n",
       "0  0.000027      0.000027  0.000019         0.000026     0.000036           1\n",
       "1  0.000027      0.000027  0.000019         0.000026     0.000031          12\n",
       "2  0.000030      0.000027  0.000019         0.000026    -0.000018           7\n",
       "3  0.000030      0.000027  0.000038         0.000027     0.000016          11\n",
       "4  0.000027      0.000027  0.000038         0.000026     0.000031          26"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_FE.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": "block",
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
